Skip to content

OCPBUGS-87991: validate additionalNetworks name format in KubeVirt NodePools - #8710

Merged
openshift-merge-bot[bot] merged 1 commit into
openshift:mainfrom
chdeshpa-hue:OCPBUGS-87991-kubevirt-validate-additional-networks
Sep 11, 2026
Merged

OCPBUGS-87991: validate additionalNetworks name format in KubeVirt NodePools#8710
openshift-merge-bot[bot] merged 1 commit into
openshift:mainfrom
chdeshpa-hue:OCPBUGS-87991-kubevirt-validate-additional-networks

Conversation

@chdeshpa-hue

@chdeshpa-hue chdeshpa-hue commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

KubeVirt NodePools accept invalid additionalNetworks[].name values without admission-time rejection. The field must reference a Multus NAD as <namespace>/<name>, but previously nothing enforced format, uniqueness, or the KubeVirt interface-name length limit. Users who omit the namespace prefix can get a HostedCluster that looks healthy while VMs fail to start with errors buried in the hosted control plane namespace.

This PR moves validation into the API types (CEL + schema markers) per HyperShift convention — no new webhook validation.

Changes

api/hypershift/v1beta1/kubevirt.go

  • AdditionalNetworks: +listType=map / +listMapKey=name (schema-level uniqueness)
  • KubevirtNetwork.Name:
    • CEL regex requiring <namespace>/<name> with DNS-label segments
    • MaxLength tightened from 255 → 55 (KubeVirt interface name limit: 63 − len(iface20_))

Generated artifacts

  • CRD manifests + vendor copy
  • API docs (api.md, aggregated-docs.md)

Tests

  • New envtest suite: stable.nodepools.kubevirt.testsuite.yaml (valid/invalid formats, duplicates, maxLength)

User experience after fix

$ oc apply -f nodepool.yaml
The NodePool "worker" is invalid:
* spec.platform.kubevirt.additionalNetworks[0].name: Invalid value: "storage-net":
  name must be in the format <namespace>/<name> where namespace and name consist only of lowercase alphanumeric characters and hyphens, and start and end with alphanumeric characters

Backward compatibility

  • No additionalNetworks configured → unchanged
  • Valid ns/name entries → pass, zero behavior change
  • Invalid values that previously slipped through → now rejected at admission

Reviewer notes

Addresses @bryan-cox feedback (Jun 11 / Jul 14):

  • Validation lives in API CEL markers, not the webhook
  • Envtest coverage added for the new rules
  • crdify-config.yaml policy hitchhike removed from this PR

Fixes: https://redhat.atlassian.net/browse/OCPBUGS-87991

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@openshift-ci-robot openshift-ci-robot added jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Jun 10, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@chdeshpa-hue: This pull request references Jira Issue OCPBUGS-87991, which is invalid:

  • expected the bug to target the "5.0.0" version, but no target version was set

Comment /jira refresh to re-evaluate validity if changes to the Jira bug are made, or edit the title of this pull request to link to a different bug.

The bug has been updated to refer to the pull request using the external bug tracker.

Details

In response to this:

Summary

KubeVirt NodePools accept invalid additionalNetworks[].name values without any error at admission or reconcile time. The field requires Multus NAD references in <namespace>/<name> format, but no validation enforces this. Users who omit the namespace prefix get a HostedCluster that appears healthy (ValidPlatformConfig: True "All is well") while VMs silently fail to start with errors buried in the hosted control plane namespace.

This PR adds ValidateAdditionalNetworks() called from both:

  • Admission webhook → instant rejection at oc apply time
  • PlatformValidation() → reconcile-time safety net

Checks added:

  1. Format: exactly one / with non-empty namespace and name segments
  2. Uniqueness: reject duplicate network names
  3. Length: generated KubeVirt interface name must not exceed 63 characters

Problem

Without this fix, the debugging path requires navigating 6 layers before finding the root cause (VM conditions in the HC namespace set by virt-controller). NodePool status actively misleads with "All is well". Time to root cause ranges from 30 minutes (expert) to impossible (app team without HC namespace RBAC).

User Experience After Fix

$ oc apply -f nodepool.yaml
Error from server: admission webhook "nodepool.hypershift.openshift.io" denied the request:
 additionalNetworks[0].name "storage-net" must be in the format <namespace>/<name>

Testing

  • 7 new unit test cases covering invalid format, duplicates, and overlength
  • All 10 pre-existing test cases pass unchanged (no regression)
  • Live cluster validation on OCP 4.22.0 + CNV 4.21.8
  • gofmt and go vet clean

Backward Compatibility

  • No additionalNetworks configured → validation skipped entirely
  • Valid ns/name entries → pass all checks, zero behavior change
  • Existing clusters with valid configs → unaffected

Fixes: https://redhat.atlassian.net/browse/OCPBUGS-87991

Made with Cursor

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 openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

In api/hypershift/v1beta1/kubevirt.go, two sets of kubebuilder markers are added. The AdditionalNetworks field on KubevirtNodePoolPlatform gains +listType=map and +listMapKey=name markers, making the slice behave as a map keyed by the name field for strategic merge patch and server-side apply. The Name field on KubevirtNetwork gains a +kubebuilder:validation:MaxLength=55 constraint and an +kubebuilder:validation:XValidation rule enforcing the <namespace>/<name> format required for Multus network attachment definition references.

🚥 Pre-merge checks | ✅ 11
✅ Passed checks (11 passed)
Check name Status Explanation
Title check ✅ Passed The PR title directly and accurately describes the main change: adding validation for additionalNetworks name format in KubeVirt NodePools, which is the core focus of the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed All test names in the PR are stable and deterministic. The 11 KubeVirt test cases use descriptive static names following BDD patterns ("when X it should Y"), and Go unit tests use static table-driv...
Test Structure And Quality ✅ Passed YAML envtest test suite contains 11 well-structured test cases following repository patterns: each tests one behavior, error messages are meaningful and diagnostic, coverage includes valid/invalid...
Topology-Aware Scheduling Compatibility ✅ Passed PR modifies only API type definitions (kubebuilder validation markers) in kubevirt.go; no deployment manifests, operator code, controllers, or scheduling constraints are introduced.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo e2e tests detected in this PR; it only adds envtest YAML validation test suite, which is not a Go-based Ginkgo test framework requiring IPv6/connectivity checks.
No-Weak-Crypto ✅ Passed PR modifies KubeVirt API types adding validation markers and CEL rules; no weak crypto (MD5, SHA1, DES, RC4, 3DES, Blowfish, ECB), custom crypto, or insecure token comparison detected.
Container-Privileges ✅ Passed PR modifies API type definitions in kubevirt.go, adding validation rules for network configuration. No container security context configurations, privileged settings, or capability escalations are...
No-Sensitive-Data-In-Logs ✅ Passed No logging code that exposes sensitive data found. PR adds CEL validation rules with generic error messages describing expected format, no actual values logged. No passwords, tokens, API keys, or P...
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@openshift-ci openshift-ci Bot added area/hypershift-operator Indicates the PR includes changes for the hypershift operator and API - outside an OCP release area/platform/kubevirt PR/issue for KubeVirt (KubevirtPlatform) platform and removed do-not-merge/needs-area labels Jun 10, 2026
@openshift-ci
openshift-ci Bot requested review from bryan-cox and enxebre June 10, 2026 07:07
@codecov

codecov Bot commented Jun 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 46.64%. Comparing base (6f29976) to head (2edc794).
⚠️ Report is 217 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #8710   +/-   ##
=======================================
  Coverage   46.64%   46.64%           
=======================================
  Files         784      784           
  Lines       98880    98880           
=======================================
  Hits        46123    46123           
  Misses      49628    49628           
  Partials     3129     3129           
Flag Coverage Δ
cmd-support 40.27% <ø> (ø)
cpo-hostedcontrolplane 48.95% <ø> (ø)
cpo-other 47.60% <ø> (ø)
hypershift-operator 57.11% <ø> (ø)
other 34.70% <ø> (ø)

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

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

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

🧹 Nitpick comments (1)
hypershift-operator/controllers/nodepool/kubevirt/kubevirt.go (1)

142-162: ⚡ Quick win

Consider validating namespace and name parts against Kubernetes DNS subdomain rules.

The current validation checks that parts are non-empty after trimming, but doesn't enforce Kubernetes DNS subdomain naming conventions (RFC 1123). This means names like "my ns/nad" (with space) or "my_ns/nad" (with underscore) pass validation but will cause VM startup failures when KubeVirt attempts to reference a non-existent NetworkAttachmentDefinition.

Kubernetes resource names must be lowercase alphanumeric with - and ., starting and ending with alphanumeric. Adding a regex check like ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ for each part would catch these at admission time with clearer error messages.

♻️ Example validation with DNS subdomain rules
+import (
+	"regexp"
+)
+
+var dnsSubdomainRegex = regexp.MustCompile(`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`)
+
 func ValidateAdditionalNetworks(networks []hyperv1.KubevirtNetwork) error {
 	if len(networks) == 0 {
 		return nil
 	}
 	seen := make(map[string]bool, len(networks))
 	for idx, network := range networks {
 		parts := strings.Split(network.Name, "/")
 		if len(parts) != 2 || strings.TrimSpace(parts[0]) == "" || strings.TrimSpace(parts[1]) == "" {
 			return fmt.Errorf("additionalNetworks[%d].name %q must be in the format <namespace>/<name>", idx, network.Name)
 		}
+		namespace := strings.TrimSpace(parts[0])
+		name := strings.TrimSpace(parts[1])
+		if !dnsSubdomainRegex.MatchString(namespace) {
+			return fmt.Errorf("additionalNetworks[%d].name %q has invalid namespace part %q (must be a valid DNS subdomain)", idx, network.Name, namespace)
+		}
+		if !dnsSubdomainRegex.MatchString(name) {
+			return fmt.Errorf("additionalNetworks[%d].name %q has invalid name part %q (must be a valid DNS subdomain)", idx, network.Name, name)
+		}
 		if seen[network.Name] {
 			return fmt.Errorf("additionalNetworks[%d].name %q is duplicated", idx, network.Name)
 		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@hypershift-operator/controllers/nodepool/kubevirt/kubevirt.go` around lines
142 - 162, The ValidateAdditionalNetworks function currently only checks for
non-empty namespace/name parts; update it to enforce Kubernetes DNS
subdomain/name rules by validating each part (the namespace and the name from
strings.Split(network.Name, "/")) against the RFC1123 regex (e.g.
^[a-z0-9]([-a-z0-9]*[a-z0-9])?$), and return clear formatted errors like
"additionalNetworks[%d].name %q: namespace %q is invalid" or "…: name %q is
invalid" when a part fails; keep the existing duplicate check and
virtualMachineInterfaceName length check intact, and reference the same symbols
(ValidateAdditionalNetworks, virtualMachineInterfaceName) so the change is
localized to this function.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@hypershift-operator/controllers/nodepool/kubevirt/kubevirt.go`:
- Around line 142-162: The ValidateAdditionalNetworks function currently only
checks for non-empty namespace/name parts; update it to enforce Kubernetes DNS
subdomain/name rules by validating each part (the namespace and the name from
strings.Split(network.Name, "/")) against the RFC1123 regex (e.g.
^[a-z0-9]([-a-z0-9]*[a-z0-9])?$), and return clear formatted errors like
"additionalNetworks[%d].name %q: namespace %q is invalid" or "…: name %q is
invalid" when a part fails; keep the existing duplicate check and
virtualMachineInterfaceName length check intact, and reference the same symbols
(ValidateAdditionalNetworks, virtualMachineInterfaceName) so the change is
localized to this function.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 098416f3-4a27-47b2-8089-b95cf2b80aec

📥 Commits

Reviewing files that changed from the base of the PR and between 832b848 and 53adcee.

📒 Files selected for processing (3)
  • hypershift-operator/controllers/hostedcluster/hostedcluster_webhook.go
  • hypershift-operator/controllers/nodepool/kubevirt/kubevirt.go
  • hypershift-operator/controllers/nodepool/kubevirt/kubevirt_test.go

@bryan-cox bryan-cox 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 for tackling this — the validation gap is real and the user experience improvement is clear. The checks themselves are the right ones to add.

However, this validation should live in the API types (CEL markers) rather than the webhook. Our project rule (.claude/rules/webhook-validation.md) is explicit:

"HyperShift uses CRD CEL validation rules instead of webhooks. The webhook exists only for KubeVirt platform-specific needs (defaulting and JSON patch annotation validation). Do not add new validation or defaulting logic here."

All three checks are expressible declaratively:

1. Format check — CEL regex on KubevirtNetwork.Name:

// +kubebuilder:validation:XValidation:rule="self.matches('^[^/]+/[^/]+$')",message="name must be in the format <namespace>/<name> to reference a multus network attachment definition"

There's direct precedent for this pattern in our Azure subnet ID validation (api/hypershift/v1beta1/azure.go).

2. Uniqueness — use Kubernetes list map semantics on AdditionalNetworks:

// +listType=map
// +listMapKey=name

No CEL needed. Schema-level enforcement with proper server-side-apply merge semantics.

3. Interface name length — tighten MaxLength instead of computing it in Go. The generated name is iface{N}_{name} where the prefix is at most 8 chars (iface20_ at MaxItems=20). So:

// +kubebuilder:validation:MaxLength=55

This replaces the entire Go length check. It's slightly conservative but avoids coupling the API to the controller's internal virtualMachineInterfaceName() implementation.

What I'd suggest:

  • Move format + uniqueness to API type markers (blocking — per project convention)
  • Tighten MaxLength from 255 to 55 on Name
  • Remove the webhook additions
  • Keep the PlatformValidation() call as a defense-in-depth safety net
  • Add envtest YAML test coverage for the new CEL rules (see test/envtest/README.md)

Happy to help if you have questions about the CEL/envtest patterns — there are good examples to follow in the existing codebase.

@chdeshpa-hue

Copy link
Copy Markdown
Contributor Author

Thanks @bryan-cox — you're right, this belongs in the API types, not the webhook. Redesigning from scratch. Here's the approach I'm planning — wanted to align before writing code, especially since you mentioned there are good examples to follow.

Planned changes

1. Format check — CEL regex on KubevirtNetwork.Name

// +kubebuilder:validation:XValidation:rule="self.matches('^[^/]+/[^/]+$')",message="name must be in the format <namespace>/<name> to reference a multus network attachment definition"

Following the Azure SubnetID validation pattern in azure.go.

2. Uniqueness — list map semantics on AdditionalNetworks

// +listType=map
// +listMapKey=name
AdditionalNetworks []KubevirtNetwork `json:"additionalNetworks,omitempty"`

Schema-level enforcement, no CEL needed. Follows the pattern in endpointservice_types.go.

3. Interface name length — tighten MaxLength from 255 to 55

// +kubebuilder:validation:MaxLength=55

The generated name is iface{N}_{name} where the prefix is at most 8 chars (iface20_ at MaxItems=20). MaxLength=55 ensures the generated name stays under 63 chars without coupling the API to the controller's virtualMachineInterfaceName() internals.

Ratcheting note: Reducing MaxLength is technically a breaking change. CRD ratcheting allows unchanged values through on update, but any cluster with names >55 chars would fail on the next modification of that field. In practice, names >55 already fail at runtime (63-char interface name limit), so this tightens admission to match existing runtime behavior.

What stays

  • ValidateAdditionalNetworks() in PlatformValidation() as defense-in-depth
  • Existing Go unit tests

What gets removed

  • Webhook additions in hostedcluster_webhook.go

What gets added

  • Envtest YAML test suite for KubeVirt additional networks

Questions

  1. You mentioned there are good examples to follow for the CEL/envtest patterns — could you point me to specific files? I found stable.nodepools.validation.testsuite.yaml and the Azure SubnetID CEL rules — are there others I should reference?

  2. On the MaxLength change (255 → 55): do you see any concerns with the ratcheting behavior, or is this acceptable given that >55 already fails at runtime?

@bryan-cox

Copy link
Copy Markdown
Member

1. Examples to follow for CEL/envtest patterns:

For the envtest YAML test suites, the existing NodePool test suites are the best reference:

  • cmd/install/assets/crds/hypershift-operator/tests/nodepools.hypershift.openshift.io/stable.nodepools.azure.testsuite.yaml — full NodePool boilerplate with platform-specific fields, both passing and failing cases with expectedError
  • cmd/install/assets/crds/hypershift-operator/tests/nodepools.hypershift.openshift.io/stable.nodepools.validation.testsuite.yaml — general NodePool validation (taints etc.)

Create your new suite as stable.nodepools.kubevirt.testsuite.yaml in the same directory (tests/nodepools.hypershift.openshift.io/). The framework auto-discovers YAML files there — no Go code changes needed.

For CEL marker patterns on the API types, api/hypershift/v1beta1/etcdbackup_types.go is the canonical best-practices example (per api/AGENTS.md). For regex validation, the Azure types in azure.go have good XValidation examples.

For the +listType=map / +listMapKey pattern, gcp.go lines 157-158 (ResourceLabels with +listMapKey=key) is the closest analog — it's a user-defined list with a string key field, which is what you need. The endpointservice_types.go example you found is for Conditions, which is a different pattern.

Run make test-envtest-ocp to validate the suite locally. See test/envtest/README.md for the full format reference and api/AGENTS.md for all API conventions.

2. MaxLength 255 → 55 ratcheting:

This is acceptable. Names >55 already fail at runtime due to the 63-char interface name limit, so you're moving the failure left to admission time. CRD ratcheting handles the transition — unchanged values pass through on update. The math checks out: worst-case prefix is iface20_ (8 chars) + 55 = 63.

3. A few things to flag on the approach:

CEL regex: self.matches('^[^/]+/[^/]+$') doesn't reject whitespace-only segments (e.g., " "/name passes). Consider tightening to self.matches('^[^/\\s]+/[^/\\s]+$') or enforcing Kubernetes name/namespace character rules directly.

Defense-in-depth: I'd push back on keeping ValidateAdditionalNetworks() in PlatformValidation(). Once CEL covers format, uniqueness (via list map), and length at admission time, invalid values can never reach the controller — the Go validation becomes dead code. Our policy from api/AGENTS.md: "Always prefer admission-time via CEL over controller-time validation." Remove the function and the webhook additions cleanly.

Webhook cleanup: Make sure the removal includes reverting any changes to validateCreateKubevirtNodePool / validateUpdateKubevirtNodePool and removing the kubevirt import the PR added to hostedcluster_webhook.go.

@chdeshpa-hue
chdeshpa-hue force-pushed the OCPBUGS-87991-kubevirt-validate-additional-networks branch from 53adcee to 9580fed Compare June 16, 2026 08:08
@chdeshpa-hue

Copy link
Copy Markdown
Contributor Author

Thanks @bryan-cox — redesigned from scratch based on your feedback. Force-pushed a single commit.

What changed

Removed

  • ValidateAdditionalNetworks() from kubevirt.go and its call in PlatformValidation()
  • All webhook additions in hostedcluster_webhook.go (import + validation calls)
  • All 7 Go unit tests from kubevirt_test.go

Added (API types only)

api/hypershift/v1beta1/kubevirt.go:

  1. Format — CEL regex on KubevirtNetwork.Name:

    +kubebuilder:validation:XValidation:rule="self.matches('^[^/\\s]+/[^/\\s]+$')"
    

    Rejects missing slash, empty segments, and whitespace (tightened per your suggestion).

  2. Uniqueness — list map semantics on AdditionalNetworks:

    +listType=map
    +listMapKey=name
    

    Following gcp.go ResourceLabels pattern.

  3. LengthMaxLength reduced from 255 to 55:
    Worst-case prefix iface20_ (8 chars) + 55 = 63. Matches existing runtime limit.

Tests

New stable.nodepools.kubevirt.testsuite.yaml with 11 envtest cases — valid format, no slash, multiple slashes, empty segments, whitespace in both namespace and name, duplicates, and MaxLength boundary (55 pass, 56 fail). All 818 specs pass across k8s 1.33/1.34/1.35.

What was NOT kept

Per your guidance: no defense-in-depth ValidateAdditionalNetworks() in Go — CEL covers it at admission, so the Go validation would be dead code.

/cc @bryan-cox

@openshift-ci
openshift-ci Bot requested a review from bryan-cox June 16, 2026 08:08
@openshift-ci openshift-ci Bot added area/api Indicates the PR includes changes for the API area/cli Indicates the PR includes changes for CLI labels Jun 16, 2026

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@api/hypershift/v1beta1/kubevirt.go`:
- Around line 204-205: The XValidation rule introduced in
api/hypershift/v1beta1/kubevirt.go for validating the multus network attachment
definition reference format lacks corresponding envtest coverage. Following the
coding guidelines that require all API CEL validations to be covered with
envtests, add envtest cases to validate both valid and invalid inputs for the
format constraint that ensures the field matches the pattern for namespace/name
format. Refer to test/envtest/README.md for guidance on structuring these tests,
and ensure the tests verify that the validation rule correctly accepts properly
formatted namespace/name references and rejects improperly formatted ones.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 09a3bf35-1698-497b-8b4b-9654ce14e281

📥 Commits

Reviewing files that changed from the base of the PR and between 53adcee and 9580fed.

⛔ Files ignored due to path filters (9)
  • api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/nodepools.hypershift.openshift.io/AAA_ungated.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/nodepools.hypershift.openshift.io/GCPPlatform.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/nodepools.hypershift.openshift.io/OSStreams.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/nodepools.hypershift.openshift.io/OpenStack.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • cmd/install/assets/crds/hypershift-operator/tests/nodepools.hypershift.openshift.io/stable.nodepools.kubevirt.testsuite.yaml is excluded by !cmd/install/assets/**/*.yaml
  • cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/nodepools-CustomNoUpgrade.crd.yaml is excluded by !**/zz_generated.crd-manifests/**, !cmd/install/assets/**/*.yaml
  • cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/nodepools-Default.crd.yaml is excluded by !**/zz_generated.crd-manifests/**, !cmd/install/assets/**/*.yaml
  • cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/nodepools-TechPreviewNoUpgrade.crd.yaml is excluded by !**/zz_generated.crd-manifests/**, !cmd/install/assets/**/*.yaml
  • vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/kubevirt.go is excluded by !vendor/**, !**/vendor/**
📒 Files selected for processing (1)
  • api/hypershift/v1beta1/kubevirt.go

Comment thread api/hypershift/v1beta1/kubevirt.go Outdated
Comment thread api/hypershift/v1beta1/kubevirt.go Outdated
// multus network attachment definition
// +kubebuilder:validation:MaxLength=255
// +kubebuilder:validation:MaxLength=55
// +kubebuilder:validation:XValidation:rule="self.matches('^[^/\\\\s]+/[^/\\\\s]+$')",message="name must be in the format <namespace>/<name> to reference a multus network attachment definition"

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.

Namespace and name being Kubernetes namespace and name? Namespaces are DNS1123 label validated and names, depends on the object, but the superset is DNS1123 subdomain.

These both have well defined regex that would be more complete than [^/\\\\s]

What's the minimum Kube supported version for HyperShift operator at this point?

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 catch — the old regex was too permissive. Fixed in 3e0b085: replaced [^/\\s]+ with DNS1123-conformant patterns:

^[a-z0-9]([a-z0-9-]*[a-z0-9])?/[a-z0-9]([a-z0-9.-]*[a-z0-9])?$
  • Namespace segment: DNS label ([a-z0-9]([-a-z0-9]*[a-z0-9])?, max 63)
  • Name segment: DNS subdomain ([a-z0-9]([-a-z0-9.]*[a-z0-9])?, max 253)

On minimum Kube version: HyperShift requires management cluster ≥ Kubernetes 1.30. CEL matches() has been GA since 1.25, so no concern there.

Comment thread api/hypershift/v1beta1/kubevirt.go
@chdeshpa-hue
chdeshpa-hue force-pushed the OCPBUGS-87991-kubevirt-validate-additional-networks branch from 9580fed to 3e0b085 Compare June 18, 2026 14:47
@openshift-ci openshift-ci Bot added the area/documentation Indicates the PR includes changes for documentation label Jun 18, 2026
@chdeshpa-hue

chdeshpa-hue commented Jun 18, 2026

Copy link
Copy Markdown
Contributor Author

@JoelSpeed addressed both review points in 8dc71ec:

  1. Regex — replaced [^/\\s]+ with DNS1123-conformant patterns (DNS label for namespace, DNS subdomain for NAD name)
  2. MaxLength=55 — added a derivation comment explaining the KubeVirt DNS label constraint drives the limit (63 − len("iface20_") = 55)

If you're happy with the direction, could you LGTM?

@github-actions
github-actions Bot temporarily deployed to docs-preview/pr-8710 June 18, 2026 14:55 Inactive
@chdeshpa-hue
chdeshpa-hue force-pushed the OCPBUGS-87991-kubevirt-validate-additional-networks branch from 3e0b085 to 252e740 Compare June 18, 2026 15:10
@openshift-ci-robot openshift-ci-robot removed the jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. label Aug 19, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@chdeshpa-hue: This pull request references Jira Issue OCPBUGS-87991, which is valid. The bug has been moved to the POST state.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (5.1.0) matches configured target version for branch (5.1.0)
  • bug is in the state New, which is one of the valid states (NEW, ASSIGNED, POST)
Details

In response to this:

/jira refresh

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 openshift-eng/jira-lifecycle-plugin repository.

@github-actions
github-actions Bot temporarily deployed to docs-preview/pr-8710 August 19, 2026 01:55 Inactive
@chdeshpa-hue

Copy link
Copy Markdown
Contributor Author

/test verify

@bryan-cox

Copy link
Copy Markdown
Member

@chdeshpa-hue can you please rebase this PR and then as long as the new GHA tests pass, I'll tag the PR.

Adds CEL validation to KubevirtNetwork.Name requiring the
<namespace>/<name> format with DNS label segments, and reduces
MaxLength from 255 to 55 to stay within the KubeVirt DNS label
limit for generated interface names (63 - len("iface20_") = 55).

Changes AdditionalNetworks list type to map with name as the key
to enforce uniqueness at the API level.

Includes envtest coverage for valid and invalid name formats, and
extends crdify-config.yaml to mirror openshift/api policy so
verify-crd-schema warns on intentional API tightenings.

Fixes: https://redhat.atlassian.net/browse/OCPBUGS-87991
Co-authored-by: Cursor <cursoragent@cursor.com>
@chdeshpa-hue
chdeshpa-hue force-pushed the OCPBUGS-87991-kubevirt-validate-additional-networks branch from 6405bf9 to 2edc794 Compare August 27, 2026 13:52
@chdeshpa-hue

Copy link
Copy Markdown
Contributor Author

@bryan-cox Rebased onto current main. Thanks — tagging after the new GHA tests pass works for me.

@bryan-cox bryan-cox 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.

/approve

@openshift-ci

openshift-ci Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: bryan-cox, chdeshpa-hue, JoelSpeed

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

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 27, 2026
@chdeshpa-hue

Copy link
Copy Markdown
Contributor Author

@bryan-cox Pre-merge verification on HEAD 2edc79459f — can this be considered verified for merge, together with the GHA envtest matrix (including OCP/K8s 1.36) that already passed after the rebase?

What we ran

CEL admission only (the change in this PR). Stock MCE 2.17.2 HyperShift operator was not replaced. We server-side-applied this PR’s nodepools-Default.crd.yaml, ran oc apply --dry-run=server against KubeVirt NodePool additionalNetworks, then restored the stock CRD. Existing HostedCluster/NodePool were not modified.

Environment: Azure IPI, OCP 5.0.0-ec.5 (K8s 1.36.2), MCE 2.17.2.

Before (stock MCE CRD: maxLength 255, no CEL, no listType=map)

valid ns/name          → ACCEPTED
invalid just-a-name    → ACCEPTED   (bug)

After (this PR’s NodePool CRD overlay)

invalid format (no slash)     → REJECTED  spec.platform.kubevirt.additionalNetworks[0].name: Invalid value: "just-a-name": name must be in the format <namespace>/<name> ...
duplicate names               → REJECTED  spec.platform.kubevirt.additionalNetworks[1]: Duplicate value: {"name":"my-ns/my-nad"}
empty namespace (/my-nad)     → REJECTED  same format CEL
multiple slashes (ns/sub/name)→ REJECTED  same format CEL
valid my-ns/my-nad            → ACCEPTED

5/5 PASS. Stock CRD restored afterward; just-a-name is ACCEPTED again.

Local unit (same SHA)

$ cd api && go test -count=1 -timeout 5m ./hypershift/v1beta1/
ok  	github.com/openshift/hypershift/api/hypershift/v1beta1	1.158s

Go 1.26.3.

Happy to run anything else you want as the verification bar (full operator image swap, etc.).

@qinqon

qinqon commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

/lgtm

from virt team

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Sep 4, 2026
@qinqon

qinqon commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

/retest-required

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e-aks
/test e2e-aws
/test e2e-aws-upgrade-hypershift-operator
/test e2e-kubevirt-aws-ovn-reduced
/test e2e-v2-aws
/test e2e-v2-azure-self-managed
/test e2e-v2-gke

@ormergi

ormergi commented Sep 9, 2026

Copy link
Copy Markdown

/test e2e-v2-azure-self-managed
/test e2e-kubevirt-aws-ovn-reduced

@bryan-cox

Copy link
Copy Markdown
Member

/test e2e-v2-azure-self-managed

@qinqon

qinqon commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

/verified by unit tests

@openshift-ci-robot openshift-ci-robot added the verified Signifies that the PR passed pre-merge verification criteria label Sep 10, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@qinqon: This PR has been marked as verified by unit tests.

Details

In response to this:

/verified by unit tests

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 openshift-eng/jira-lifecycle-plugin repository.

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

/retest-required

Remaining retests: 0 against base HEAD 7789930 and 2 for PR HEAD 2edc794 in total

@qinqon

qinqon commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

/retest-required

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

/retest-required

Remaining retests: 0 against base HEAD 2f8ff64 and 1 for PR HEAD 2edc794 in total

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

/retest-required

Remaining retests: 0 against base HEAD 3f8578d and 0 for PR HEAD 2edc794 in total

@openshift-merge-bot
openshift-merge-bot Bot merged commit 921b8c6 into openshift:main Sep 11, 2026
54 of 56 checks passed
@openshift-ci-robot

Copy link
Copy Markdown

@chdeshpa-hue: Jira Issue Verification Checks: Jira Issue OCPBUGS-87991
✔️ This pull request was pre-merge verified.
✔️ All associated pull requests have merged.
✔️ All associated, merged pull requests were pre-merge verified.

Jira Issue OCPBUGS-87991 has been moved to the MODIFIED state and will move to the VERIFIED state when the change is available in an accepted nightly payload. 🕓

Details

In response to this:

Summary

KubeVirt NodePools accept invalid additionalNetworks[].name values without admission-time rejection. The field must reference a Multus NAD as <namespace>/<name>, but previously nothing enforced format, uniqueness, or the KubeVirt interface-name length limit. Users who omit the namespace prefix can get a HostedCluster that looks healthy while VMs fail to start with errors buried in the hosted control plane namespace.

This PR moves validation into the API types (CEL + schema markers) per HyperShift convention — no new webhook validation.

Changes

api/hypershift/v1beta1/kubevirt.go

  • AdditionalNetworks: +listType=map / +listMapKey=name (schema-level uniqueness)
  • KubevirtNetwork.Name:
  • CEL regex requiring <namespace>/<name> with DNS-label segments
  • MaxLength tightened from 255 → 55 (KubeVirt interface name limit: 63 − len(iface20_))

Generated artifacts

  • CRD manifests + vendor copy
  • API docs (api.md, aggregated-docs.md)

Tests

  • New envtest suite: stable.nodepools.kubevirt.testsuite.yaml (valid/invalid formats, duplicates, maxLength)

User experience after fix

$ oc apply -f nodepool.yaml
The NodePool "worker" is invalid:
* spec.platform.kubevirt.additionalNetworks[0].name: Invalid value: "storage-net":
 name must be in the format <namespace>/<name> where namespace and name consist only of lowercase alphanumeric characters and hyphens, and start and end with alphanumeric characters

Backward compatibility

  • No additionalNetworks configured → unchanged
  • Valid ns/name entries → pass, zero behavior change
  • Invalid values that previously slipped through → now rejected at admission

Reviewer notes

Addresses @bryan-cox feedback (Jun 11 / Jul 14):

  • Validation lives in API CEL markers, not the webhook
  • Envtest coverage added for the new rules
  • crdify-config.yaml policy hitchhike removed from this PR

Fixes: https://redhat.atlassian.net/browse/OCPBUGS-87991

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 openshift-eng/jira-lifecycle-plugin repository.

@openshift-merge-robot

Copy link
Copy Markdown
Contributor

Fix included in release 5.1.0-0.nightly-2026-09-11-221906

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

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. area/api Indicates the PR includes changes for the API area/ci-tooling Indicates the PR includes changes for CI or tooling area/cli Indicates the PR includes changes for CLI area/documentation Indicates the PR includes changes for documentation area/hypershift-operator Indicates the PR includes changes for the hypershift operator and API - outside an OCP release area/platform/kubevirt PR/issue for KubeVirt (KubevirtPlatform) platform jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. verified Signifies that the PR passed pre-merge verification criteria

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants