Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions api/hypershift/v1beta1/kubevirt.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ type KubevirtNodePoolPlatform struct {
// additionalNetworks specify the extra networks attached to the nodes
//
// +optional
// +listType=map
// +listMapKey=name
// +kubebuilder:validation:MaxItems=20
AdditionalNetworks []KubevirtNetwork `json:"additionalNetworks,omitempty"`

Expand Down Expand Up @@ -198,8 +200,14 @@ type KubevirtNodePoolPlatform struct {
type KubevirtNetwork struct {
// name specify the network attached to the nodes
// it is a value with the format "[namespace]/[name]" to reference the
// multus network attachment definition
// +kubebuilder:validation:MaxLength=255
// multus network attachment definition, where namespace and name consist
// only of lowercase alphanumeric characters and hyphens, and start and
// end with alphanumeric characters
// +kubebuilder:validation:MaxLength=55
Comment thread
JoelSpeed marked this conversation as resolved.

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.

Wouldn't this regress existing clusters?

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.

No — CRD validation ratcheting (GA since K8s 1.28; HyperShift requires ≥1.30) protects existing clusters:

  • MaxLength 255→55 and CEL regex: Both are ratcheted per-field. Unchanged values on existing NodePools skip the new validation entirely. Any name that would fail these checks already fails at KubeVirt runtime — the generated iface{N}_{ns}-{name} exceeds the 63-char DNS label limit or Multus can't resolve the NAD.

  • listType=map + listMapKey=name: Map key uniqueness is a structural constraint and is NOT ratcheted per KEP-4008. But duplicate additionalNetworks entries already cause VM startup failures (interface name collision), so no working cluster has them. The listType=map change actually helps — it gives per-element ratcheting (only changed/added elements are validated) vs atomic semantics where the entire list is revalidated on any change.

The net effect is moving the failure left from silent runtime failure to clear admission rejection, with ratcheting ensuring existing deployments are unaffected on upgrade.

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 the explanation!

// MaxLength=55: KubeVirt requires Interface.Name to be a DNS label (max 63 chars).
// The generated name is "iface{N}_{namespace}-{name}" where N≤20 (MaxItems),
// giving a max prefix of "iface20_" (8 chars), leaving 55 chars for namespace/name.
// +kubebuilder:validation:XValidation:rule="self.matches('^[a-z0-9]([a-z0-9-]*[a-z0-9])?/[a-z0-9]([a-z0-9-]*[a-z0-9])?$')",message="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"

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.

This is good, can we also get this style explanation of the format in the godoc itself so that oc explain explains in the same way. API LGTM after that

// +required
Name string `json:"name"`
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1103,14 +1103,28 @@ spec:
description: |-
name specify the network attached to the nodes
it is a value with the format "[namespace]/[name]" to reference the
multus network attachment definition
maxLength: 255
multus network attachment definition, where namespace and name consist
only of lowercase alphanumeric characters and hyphens, and start and
end with alphanumeric characters
MaxLength=55: KubeVirt requires Interface.Name to be a DNS label (max 63 chars).
The generated name is "iface{N}_{namespace}-{name}" where N≤20 (MaxItems),
giving a max prefix of "iface20_" (8 chars), leaving 55 chars for namespace/name.
maxLength: 55
type: string
x-kubernetes-validations:
- message: 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
rule: self.matches('^[a-z0-9]([a-z0-9-]*[a-z0-9])?/[a-z0-9]([a-z0-9-]*[a-z0-9])?$')
required:
- name
type: object
maxItems: 20
type: array
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
attachDefaultNetwork:
default: true
description: |-
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1371,14 +1371,28 @@ spec:
description: |-
name specify the network attached to the nodes
it is a value with the format "[namespace]/[name]" to reference the
multus network attachment definition
maxLength: 255
multus network attachment definition, where namespace and name consist
only of lowercase alphanumeric characters and hyphens, and start and
end with alphanumeric characters
MaxLength=55: KubeVirt requires Interface.Name to be a DNS label (max 63 chars).
The generated name is "iface{N}_{namespace}-{name}" where N≤20 (MaxItems),
giving a max prefix of "iface20_" (8 chars), leaving 55 chars for namespace/name.
maxLength: 55
type: string
x-kubernetes-validations:
- message: 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
rule: self.matches('^[a-z0-9]([a-z0-9-]*[a-z0-9])?/[a-z0-9]([a-z0-9-]*[a-z0-9])?$')
required:
- name
type: object
maxItems: 20
type: array
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
attachDefaultNetwork:
default: true
description: |-
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1136,14 +1136,28 @@ spec:
description: |-
name specify the network attached to the nodes
it is a value with the format "[namespace]/[name]" to reference the
multus network attachment definition
maxLength: 255
multus network attachment definition, where namespace and name consist
only of lowercase alphanumeric characters and hyphens, and start and
end with alphanumeric characters
MaxLength=55: KubeVirt requires Interface.Name to be a DNS label (max 63 chars).
The generated name is "iface{N}_{namespace}-{name}" where N≤20 (MaxItems),
giving a max prefix of "iface20_" (8 chars), leaving 55 chars for namespace/name.
maxLength: 55
type: string
x-kubernetes-validations:
- message: 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
rule: self.matches('^[a-z0-9]([a-z0-9-]*[a-z0-9])?/[a-z0-9]([a-z0-9-]*[a-z0-9])?$')
required:
- name
type: object
maxItems: 20
type: array
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
attachDefaultNetwork:
default: true
description: |-
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1103,14 +1103,28 @@ spec:
description: |-
name specify the network attached to the nodes
it is a value with the format "[namespace]/[name]" to reference the
multus network attachment definition
maxLength: 255
multus network attachment definition, where namespace and name consist
only of lowercase alphanumeric characters and hyphens, and start and
end with alphanumeric characters
MaxLength=55: KubeVirt requires Interface.Name to be a DNS label (max 63 chars).
The generated name is "iface{N}_{namespace}-{name}" where N≤20 (MaxItems),
giving a max prefix of "iface20_" (8 chars), leaving 55 chars for namespace/name.
maxLength: 55
type: string
x-kubernetes-validations:
- message: 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
rule: self.matches('^[a-z0-9]([a-z0-9-]*[a-z0-9])?/[a-z0-9]([a-z0-9-]*[a-z0-9])?$')
required:
- name
type: object
maxItems: 20
type: array
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
attachDefaultNetwork:
default: true
description: |-
Expand Down
Loading
Loading